package level.state;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import core.Constants;

public class StateReader
{
	public static void initiateBlankState(State state, File file)
	{
		if (file != null)
			state.setFile(new File(file.getAbsolutePath()));
		else
			state.setFile(null);
		state.setLayers(new HashMap<String, StateLayer>(Constants.CAPACITY,
				Constants.LOADFACTOR));
		for (int i = 0; i < Constants.TILE_LAYER_NAMES.length; i++)
		{
			StateTileLayer layer = new StateTileLayer(
					Constants.TILE_LAYER_NAMES[i], Constants.TILE_Z_ORDER[i]);
			state.getLayers().put(Constants.TILE_LAYER_NAMES[i], layer);
		}
		// Add other layer type inits here
	}

	public static State open(File file)
	{
		State state = new State();
		initiateBlankState(state, file);
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder dBuilder;
		try
		{
			dBuilder = dbFactory.newDocumentBuilder();
			Document doc = dBuilder.parse(file);
			doc.getDocumentElement().normalize();
			Iterator<String> iterator = StateHandler.getIterator(state);
			while (iterator.hasNext())
			{
				String layerName = iterator.next();
				StateLayer layer = StateHandler.getLayer(state, layerName);
				if (layer instanceof StateTileLayer)
					open((StateTileLayer) layer, doc);
			}
		}
		catch (ParserConfigurationException | SAXException | IOException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return state;
	}

	private static void open(StateTileLayer layer, Document doc)
	{
		NodeList nList = doc.getElementsByTagName(layer.getName());
		if (nList.getLength() != 0)
		{
			for (int i = 0; i < nList.getLength(); i++)
			{
				Node nNode = nList.item(i);
				if (nNode.getNodeType() == Node.ELEMENT_NODE)
				{
					Element nElement = (Element) nNode;
					NodeList eList = nElement.getElementsByTagName("Tile");
					if (eList.getLength() != 0)
					{

						for (int j = 0; j < eList.getLength(); j++)
						{
							Tile tile = new Tile();
							Node eNode = eList.item(j);
							if (eNode.getNodeType() == Node.ELEMENT_NODE)
							{
								Element eElement = (Element) eNode;
								tile.setIconPath(getTagValue("Image", eElement));
								tile.setX(Integer.parseInt(getTagValue("x",
										eElement)));
								tile.setY(Integer.parseInt(getTagValue("y",
										eElement)));
								tile.setW(Integer.parseInt(getTagValue("w",
										eElement)));
								tile.setH(Integer.parseInt(getTagValue("h",
										eElement)));
								tile.setSx(Integer.parseInt(getTagValue("sx",
										eElement)));
								tile.setSy(Integer.parseInt(getTagValue("sy",
										eElement)));
								tile.setSw(Integer.parseInt(getTagValue("sw",
										eElement)));
								tile.setSh(Integer.parseInt(getTagValue("sh",
										eElement)));
								StateHandler.addTile(layer, tile);
							}
						}
					}
				}
			}
		}
		// debugPrintTileLayer(layer);
	}

	private static String getTagValue(String string, Element eElement)
	{
		NodeList nlList = eElement.getElementsByTagName(string).item(0)
				.getChildNodes();
		Node nValue = (Node) nlList.item(0);
		return nValue.getNodeValue();
	}

	public static void debugPrintState(State state)
	{
		if (state != null)
		{
			Iterator<String> iterator = StateHandler.getIterator(state);
			while (iterator.hasNext())
			{
				String layerName = iterator.next();
				debugPrintTileLayer((StateTileLayer) state.getLayers().get(
						layerName));
			}
		}
	}

	private static void debugPrintTileLayer(StateTileLayer layer)
	{
		ArrayList<Tile> tiles = layer.getTiles();
		if (tiles.size() != 0)
		{
			for (Tile tile : tiles)
				System.out.println(tile.getX() + "  " + tile.getY());
		}
	}
}
